package com.imooc.business.util;

import org.apache.commons.lang3.time.FastDateFormat;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @Author Tim
 * @Description:
 * @Version 1.0
 */
public class InnerDateUtil {

    private static final int[] ARR_INFO = new int[]{19416, 19168, 42352, 21717, 53856, 55632, 91476, 22176, 39632, 21970, 19168, 42422, 42192, 53840, 119381, 46400, 54944, 44450, 38320, 84343, 18800, 42160, 46261, 27216, 27968, 109396, 11104, 38256, 21234, 18800, 25958, 54432, 59984, 28309, 23248, 11104, 100067, 37600, 116951, 51536, 54432, 120998, 46416, 22176, 107956, 9680, 37584, 53938, 43344, 46423, 27808, 46416, 86869, 19872, 42448, 83315, 21200, 43432, 59728, 27296, 44710, 43856, 19296, 43748, 42352, 21088, 62051, 55632, 23383, 22176, 38608, 19925, 19152, 42192, 54484, 53840, 54616, 46400, 46496, 103846, 38320, 18864, 43380, 42160, 45690, 27216, 27968, 44870, 43872, 38256, 19189, 18800, 25776, 29859, 59984, 27480, 21952, 43872, 38613, 37600, 51552, 55636, 54432, 55888, 30034, 22176, 43959, 9680, 37584, 51893, 43344, 46240, 47780, 44368, 21977, 19360, 42416, 86390, 21168, 43312, 31060, 27296, 44368, 23378, 19296, 42726, 42208, 53856, 60005, 54576, 23200, 30371, 38608, 19415, 19152, 42192, 118966, 53840, 54560, 56645, 46496, 22224, 21938, 18864, 42359, 42160, 43600, 111189, 27936, 44448};


    protected static Calendar convertToCalendar(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }

    protected static String getSeasonType(Date date) {
        Date springStartDate = getSemesterStartDate(date);
        Date springEndDate = getSemesterEndDate(date);
        return (!date.after(springStartDate) || !date.before(springEndDate)) && 
                !formatDate(date, "yyyy-MM-dd").equals(formatDate(springStartDate, "yyyy-MM-dd")) && 
                !formatDate(date, "yyyy-MM-dd").equals(formatDate(springEndDate, "yyyy-MM-dd")) ? "2" : "1";
    }

    protected static Date getSemesterStartDate(Date date) {
        String year = getYear(date);
        Date beginDate = parseDate(Integer.parseInt(year) + 1 + "-01-08", "yyyy-MM-dd");
        return parseDate(lunar2Solar(beginDate), "yyyy-MM-dd");
    }

    protected static Date getSemesterEndDate(Date date) {
        String year = getYear(date);
        return parseDate(Integer.parseInt(year) + 1 + "-08-31", "yyyy-MM-dd");
    }

    protected static String getYear(Date date) {
        if (date == null) {
            return "----";
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int month = cal.get(2) + 1;
        if (month < 9) {
            cal.add(1, -1);
        }
        return String.valueOf(cal.get(1));
    }

    public static String formatDate(Date date, String pattern){
        FastDateFormat df = FastDateFormat.getInstance(pattern);
        return df.format(date);
    }

    public static Date parseDate(String date, String pattern){
        try {
            FastDateFormat df = FastDateFormat.getInstance(pattern);
            return df.parse(date);
        } catch (Exception e){
            return null;
        }
    }

    public static Date parseNormalDate(String date){
        try {
            FastDateFormat df = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
            return df.parse(date);
        } catch (Exception e){
            return null;
        }
    }


    /**
     * 阴历转阳历
     * @param date
     * @return
     */
    protected static String lunar2Solar(Date date) {
        if (date == null) {
            throw new RuntimeException("日期不能为空");
        } else {
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            int lunarYear = cal.get(1);
            int lunarMonth = cal.get(2) + 1;
            int lunarDay = cal.get(5);
            int leapMonth = getLeapMonth(lunarYear);
            boolean leapMonthFlag = leapMonth != 0 && leapMonth == lunarMonth;
            checkLunarDate(lunarYear, lunarMonth, lunarDay, leapMonthFlag);
            int offset = 0;

            int temp;
            int tempMonthDaysCount;
            for(temp = 1900; temp < lunarYear; ++temp) {
                tempMonthDaysCount = getYearDays(temp);
                offset += tempMonthDaysCount;
            }

            if (leapMonthFlag && leapMonth != lunarMonth) {
                throw new RuntimeException("您输入的闰月标志有误！");
            } else {
                if (leapMonth == 0 || lunarMonth < leapMonth || lunarMonth == leapMonth && !leapMonthFlag) {
                    for(temp = 1; temp < lunarMonth; ++temp) {
                        tempMonthDaysCount = getMonthDays(lunarYear, temp);
                        offset += tempMonthDaysCount;
                    }

                    if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
                        throw new RuntimeException("不合法的农历日期！");
                    }

                    offset += lunarDay;
                } else {
                    for(temp = 1; temp < lunarMonth; ++temp) {
                        tempMonthDaysCount = getMonthDays(lunarYear, temp);
                        offset += tempMonthDaysCount;
                    }

                    if (lunarMonth > leapMonth) {
                        temp = getLeapMonthDays(lunarYear);
                        offset += temp;
                        if (lunarDay > getMonthDays(lunarYear, lunarMonth)) {
                            throw new RuntimeException("不合法的农历日期！");
                        }

                        offset += lunarDay;
                    } else {
                        temp = getMonthDays(lunarYear, lunarMonth);
                        offset += temp;
                        if (lunarDay > getLeapMonthDays(lunarYear)) {
                            throw new RuntimeException("不合法的农历日期！");
                        }

                        offset += lunarDay;
                    }
                }

                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
                Date myDate = null;

                try {
                    myDate = formatter.parse("1900-01-30");
                    Calendar c = Calendar.getInstance();
                    c.setTime(myDate);
                    c.add(5, offset);
                    myDate = c.getTime();
                    return formatter.format(myDate);
                } catch (Exception var11) {
                    var11.printStackTrace();
                    return null;
                }
            }
        }
    }

    private static int getLeapMonth(int year) {
        return ARR_INFO[year - 1900] & 15;
    }

    private static int getLeapMonthDays(int year) {
        if (getLeapMonth(year) != 0) {
            return (ARR_INFO[year - 1900] & 983040) == 0 ? 29 : 30;
        } else {
            return 0;
        }
    }

    private static int getMonthDays(int lunarYeay, int month) throws RuntimeException {
        if (month <= 31 && month >= 0) {
            int bit = 1 << 16 - month;
            return (ARR_INFO[lunarYeay - 1900] & '\uffff' & bit) == 0 ? 29 : 30;
        } else {
            throw new RuntimeException("月份有错！");
        }
    }

    private static int getYearDays(int year) {
        int sum = 348;

        for(int i = 32768; i >= 8; i >>= 1) {
            if ((ARR_INFO[year - 1900] & '\ufff0' & i) != 0) {
                ++sum;
            }
        }

        return sum + getLeapMonthDays(year);
    }

    private static void checkLunarDate(int lunarYear, int lunarMonth, int lunarDay, boolean leapMonthFlag) throws RuntimeException {
        if (lunarYear >= 1900 && lunarYear <= 2049) {
            if (lunarMonth >= 1 && lunarMonth <= 12) {
                if (lunarDay >= 1 && lunarDay <= 30) {
                    int leap = getLeapMonth(lunarYear);
                    if (leapMonthFlag && lunarMonth != leap) {
                        throw new RuntimeException("非法闰月！");
                    }
                } else {
                    throw new RuntimeException("非法农历天数！");
                }
            } else {
                throw new RuntimeException("非法农历月份！");
            }
        } else {
            throw new RuntimeException("非法农历年份！");
        }
    }
}
